use crate::config::CodeStyleConfig;
use crate::core::{BuildConfiguration, Project, ProjectType, QtSettings, Solution, BuildSettings};
use crate::generators::Generator;
use crate::Result;
use std::fs;
use std::path::{Path, PathBuf};

// 在编译时嵌入配置文件内容
const CLANG_FORMAT_TEMPLATE: &str = include_str!("../../config/.clang-format");
const CLANG_TIDY_TEMPLATE: &str = include_str!("../../config/.clang-tidy");

pub struct XmakeGenerator;

impl Generator for XmakeGenerator {
    fn generate(&self, solution: &Solution, project_root: &Path, code_style: &CodeStyleConfig) -> Result<()> {
        // 获取源目录（vcxproj 或 sln 文件所在目录）
        let source_dir = solution.source_directory
            .as_ref()
            .map(|p| p.as_path())
            .unwrap_or(project_root);

        // 判断是否需要层级化结构
        let needs_hierarchy = self.is_in_subdirectory(source_dir, project_root);

        if needs_hierarchy {
            // 生成层级化结构
            self.generate_hierarchical(solution, project_root, source_dir)?;
        } else {
            // 直接生成单一 xmake.lua
            fs::create_dir_all(project_root)?;
            let xmake_content = self.generate_xmake_lua(solution, project_root)?;
            let output_file = project_root.join("xmake.lua");
            fs::write(&output_file, xmake_content)?;
            log::info!("Generated xmake.lua at: {}", output_file.display());
        }

        // 生成代码风格配置文件
        self.generate_code_style_files(project_root, code_style)?;

        Ok(())
    }

    fn file_extension(&self) -> &str {
        "lua"
    }
}

impl XmakeGenerator {
    pub fn new() -> Self {
        Self
    }

    /// 生成代码风格配置文件（.clang-format 和 .clang-tidy）
    fn generate_code_style_files(&self, project_root: &Path, code_style: &CodeStyleConfig) -> Result<()> {
        // 生成 .clang-format
        if code_style.generate_clang_format {
            let clang_format_path = project_root.join(".clang-format");
            fs::write(&clang_format_path, CLANG_FORMAT_TEMPLATE)?;
            log::info!("Generated .clang-format at: {}", clang_format_path.display());
        }

        // 生成 .clang-tidy
        if code_style.generate_clang_tidy {
            let clang_tidy_path = project_root.join(".clang-tidy");
            fs::write(&clang_tidy_path, CLANG_TIDY_TEMPLATE)?;
            log::info!("Generated .clang-tidy at: {}", clang_tidy_path.display());
        }

        Ok(())
    }

    /// 移除 Windows 的扩展路径前缀 `\\?\`
    /// 在 Windows 上，canonicalize() 可能会返回 `\\?\C:\path` 格式的路径
    /// 这会导致路径比较和 strip_prefix 操作失败
    fn normalize_path(path: &Path) -> PathBuf {
        let path_str = path.to_string_lossy();
        let value = path_str.as_ref();

        // Windows 扩展路径前缀
        if let Some(stripped) = value.strip_prefix(r"\\?\UNC\") {
            let mut prefixed = String::from(r"\\");
            prefixed.push_str(stripped);
            PathBuf::from(prefixed)
        } else if let Some(stripped) = value.strip_prefix(r"\??\UNC\") {
            let mut prefixed = String::from(r"\\");
            prefixed.push_str(stripped);
            PathBuf::from(prefixed)
        } else if value.starts_with(r"\\?\") {
            PathBuf::from(&value[4..])
        } else if value.starts_with(r"\??\") {
            PathBuf::from(&value[4..])
        } else {
            path.to_path_buf()
        }
    }

    /// 判断源目录是否在项目根目录的子目录中
    fn is_in_subdirectory(&self, source_dir: &Path, project_root: &Path) -> bool {
        // 尝试规范化路径并移除 Windows 前缀
        let source_canonical = source_dir.canonicalize()
            .ok()
            .map(|p| Self::normalize_path(&p))
            .unwrap_or_else(|| source_dir.to_path_buf());

        let root_canonical = project_root.canonicalize()
            .ok()
            .map(|p| Self::normalize_path(&p))
            .unwrap_or_else(|| project_root.to_path_buf());

        // 比较规范化后的路径
        if let Ok(relative) = source_canonical.strip_prefix(&root_canonical) {
            return relative.components().count() > 0;
        }

        // 如果无法规范化，直接比较原始路径
        if let Ok(relative) = source_dir.strip_prefix(project_root) {
            relative.components().count() > 0
        } else {
            false
        }
    }

    /// 生成层级化的 xmake.lua 文件结构
    fn generate_hierarchical(
        &self,
        solution: &Solution,
        project_root: &Path,
        source_dir: &Path,
    ) -> Result<()> {
        // 规范化路径，移除 Windows 的 \\?\ 前缀
        let normalized_root = project_root.canonicalize()
            .ok()
            .map(|p| Self::normalize_path(&p))
            .unwrap_or_else(|| project_root.to_path_buf());

        let normalized_source = source_dir.canonicalize()
            .ok()
            .map(|p| Self::normalize_path(&p))
            .unwrap_or_else(|| source_dir.to_path_buf());

        // 计算源目录相对于项目根目录的路径
        let relative_source = normalized_source.strip_prefix(&normalized_root)
            .map_err(|_| crate::BuildMigrateError::Generator(
                format!("Cannot compute relative path from {} to {}",
                    normalized_root.display(), normalized_source.display())
            ))?;

        // 生成主 xmake.lua（写入项目根目录）
        fs::create_dir_all(&normalized_root)?;
        let root_xmake = self.generate_root_xmake(relative_source)?;
        let root_file = normalized_root.join("xmake.lua");
        fs::write(&root_file, root_xmake)?;
        log::info!("Generated root xmake.lua at: {}", root_file.display());

        // 生成子 xmake.lua（写入源目录）
        fs::create_dir_all(&normalized_source)?;
        let sub_xmake = self.generate_sub_xmake(solution, &normalized_source)?;
        let sub_file = normalized_source.join("xmake.lua");
        fs::write(&sub_file, sub_xmake)?;
        log::info!("Generated sub xmake.lua at: {}", sub_file.display());

        Ok(())
    }

    /// 生成项目根目录的主 xmake.lua 文件
    fn generate_root_xmake(&self, subdirectory: &Path) -> Result<String> {
        let mut content = String::new();

        // 添加注释和基本配置
        content.push_str("-- xmake.lua generated by build_migrate\n");
        content.push_str("-- https://xmake.io/\n\n");
        content.push_str("set_xmakever(\"2.7.1\")\n\n");

        // 添加模式配置
        content.push_str("-- 添加构建模式\n");
        content.push_str("add_rules(\"mode.debug\", \"mode.release\")\n\n");

        // 包含子项目
        let subdir_str = subdirectory.to_string_lossy().replace('\\', "/");
        content.push_str("-- Include sub-projects\n");
        content.push_str(&format!("includes(\"{}\")\n", subdir_str));

        Ok(content)
    }

    /// 生成子目录的 xmake.lua 文件（包含具体的 target 定义）
    fn generate_sub_xmake(&self, solution: &Solution, output_dir: &Path) -> Result<String> {
        let mut content = String::new();

        // 为每个项目生成target
        for project in &solution.projects {
            content.push_str(&self.generate_target(project, &output_dir)?);
            content.push('\n');
        }

        Ok(content)
    }

    /// 生成文件列表的通用函数
    fn generate_file_list(
        &self,
        function_name: &str,
        files: &[String],
        indent_level: usize,
    ) -> String {
        if files.is_empty() {
            return String::new();
        }

        let indent = "    ".repeat(indent_level);
        let item_indent = "    ".repeat(indent_level + 1);
        let mut content = String::new();

        content.push_str(&format!("{}{}(\n", indent, function_name));
        for (i, file) in files.iter().enumerate() {
            if i == files.len() - 1 {
                content.push_str(&format!("{}\"{}\"\n", item_indent, file));
            } else {
                content.push_str(&format!("{}\"{}\",\n", item_indent, file));
            }
        }
        content.push_str(&format!("{})\n", indent));

        content
    }

    /// 生成路径文件列表的通用函数
    fn generate_path_file_list(
        &self,
        function_name: &str,
        files: &[std::path::PathBuf],
        output_dir: &Path,
        indent_level: usize,
    ) -> String {
        if files.is_empty() {
            return String::new();
        }

        let normalized_files: Vec<String> = files
            .iter()
            .filter_map(|file| {
                if let Ok(relative_path) = file.strip_prefix(output_dir) {
                    Some(relative_path.to_string_lossy().replace('\\', "/"))
                } else {
                    Some(file.to_string_lossy().replace('\\', "/"))
                }
            })
            .collect();

        self.generate_file_list(function_name, &normalized_files, indent_level)
    }

    fn generate_xmake_lua(&self, solution: &Solution, output_dir: &Path) -> Result<String> {
        let mut content = String::new();

        // 确定输出目录
        let output_dir = if output_dir.is_dir() {
            output_dir.to_path_buf()
        } else {
            output_dir.parent()
                .map(|p| p.to_path_buf())
                .unwrap_or_else(|| PathBuf::from("."))
        };

        // 添加xmake版本和模式设置
        content.push_str("-- xmake.lua generated by build_migrate\n");
        content.push_str("-- https://xmake.io/\n\n");
        content.push_str("set_xmakever(\"2.7.1\")\n\n");

        // 添加模式配置
        content.push_str("-- 添加构建模式\n");
        content.push_str("add_rules(\"mode.debug\", \"mode.release\")\n\n");

        // 为每个项目生成target
        for project in &solution.projects {
            content.push_str(&self.generate_target(project, &output_dir)?);
            content.push('\n');
        }

        Ok(content)
    }

    fn generate_target(&self, project: &Project, output_dir: &Path) -> Result<String> {
        let mut target_content = String::new();

        // 开始target定义
        target_content.push_str(&format!("-- Target: {}\n", project.name));
        target_content.push_str(&format!("target(\"{}\")\n", project.name));

        // 设置目标类型
        let kind = match project.project_type {
            ProjectType::Executable => "binary",
            ProjectType::StaticLibrary => "static",
            ProjectType::DynamicLibrary => "shared",
        };
        target_content.push_str(&format!("    set_kind(\"{}\")\n", kind));

        // 检查是否是 Qt 项目
        let has_qt = project
            .configurations
            .values()
            .any(|settings| settings.qt_settings.enabled);
        if has_qt {
            target_content.push_str("\n    -- Qt framework setup\n");

            // 获取第一个启用 Qt 的配置来提取基本信息
            if let Some(qt_config) = project
                .configurations
                .values()
                .find(|settings| settings.qt_settings.enabled)
            {
                // 添加 Qt 规则
                target_content.push_str("    add_rules(\"qt.widgetapp\")\n");

                // 添加 Qt 版本（如果有）
                if let Some(version) = &qt_config.qt_settings.version {
                    target_content.push_str(&format!(
                        "    set_values(\"qt.version\", \"{}\")\n",
                        version
                    ));
                }

                // 添加 Qt 模块
                if !qt_config.qt_settings.modules.is_empty() {
                    let qt_modules: Vec<String> = qt_config
                        .qt_settings
                        .modules
                        .iter()
                        .map(|module| format!("Qt{}", self.map_qt_module(module)))
                        .collect();
                    target_content.push_str(&self.generate_file_list(
                        "add_frameworks",
                        &qt_modules,
                        1,
                    ));
                }
            }
        }

        // 设置 C++ 标准（优先使用有语言标准设置的配置）
        let language_standard = project.configurations.values()
            .find_map(|settings| settings.language_standard.as_ref())
            .or_else(|| {
                // 如果所有配置都没有语言标准，使用默认值
                None
            });
        
        if let Some(standard) = language_standard {
            target_content.push_str(&format!("    set_languages(\"{}\")\n", standard));
        }

        // 处理构建配置 - 按照固定顺序：Debug, Release, 其他自定义配置
        let mut sorted_configs: Vec<(&BuildConfiguration, &BuildSettings)> = project.configurations.iter().collect();
        sorted_configs.sort_by(|a, b| {
            match (a.0, b.0) {
                (BuildConfiguration::Debug, BuildConfiguration::Debug) => std::cmp::Ordering::Equal,
                (BuildConfiguration::Debug, _) => std::cmp::Ordering::Less,
                (_, BuildConfiguration::Debug) => std::cmp::Ordering::Greater,
                (BuildConfiguration::Release, BuildConfiguration::Release) => std::cmp::Ordering::Equal,
                (BuildConfiguration::Release, BuildConfiguration::Custom(_)) => std::cmp::Ordering::Less,
                (BuildConfiguration::Custom(_), BuildConfiguration::Release) => std::cmp::Ordering::Greater,
                (BuildConfiguration::Custom(a), BuildConfiguration::Custom(b)) => a.as_str().cmp(b.as_str()),
            }
        });
        
        for (config, settings) in sorted_configs {
            match config {
                BuildConfiguration::Debug => {
                    target_content.push_str("    -- Debug configuration\n");
                    target_content.push_str("    if is_mode(\"debug\") then\n");
                }
                BuildConfiguration::Release => {
                    target_content.push_str("    -- Release configuration\n");
                    target_content.push_str("    if is_mode(\"release\") then\n");
                }
                BuildConfiguration::Custom(name) => {
                    target_content.push_str(&format!("    -- {} configuration\n", name));
                    target_content.push_str(&format!(
                        "    if is_mode(\"{}\") then\n",
                        name.to_lowercase()
                    ));
                }
            }

            // 添加此配置中不被排除的源文件
            if !project.source_files.is_empty() {
                let config_specific_files: Vec<String> = project
                    .source_files
                    .iter()
                    .filter_map(|f| {
                        let is_excluded = f.is_excluded_in_config(&config);
                        let include_in_build = f.include_in_build;
                        
                        // 排除所有 MOC 生成的 CPP 文件，因为它们应该由 xmake/Qt 工具动态生成
                        let is_moc_file = {
                            let path_str = f.path.to_string_lossy();
                            // 从路径中提取文件名，支持 Windows 和 Unix 路径分隔符
                            let filename = path_str.split(['\\', '/']).last().unwrap_or("");
                            let result = filename.starts_with("moc_") && filename.ends_with(".cpp");
                            result
                        };
                        
                        let should_include = include_in_build && !is_excluded && !is_moc_file;
                        
                        
                        if should_include {
                            // 先尝试计算相对于输出目录的相对路径
                            if let Ok(relative_path) = f.path.strip_prefix(output_dir) {
                                Some(relative_path.to_string_lossy().replace('\\', "/"))
                            } else {
                                // 如果无法计算相对路径，直接使用文件路径并规范化
                                Some(f.path.to_string_lossy().replace('\\', "/"))
                            }
                        } else {
                            log::debug!("File: {}, Config: {:?}, IncludeInBuild: {}, IsExcluded: {}, ShouldInclude: {}", 
                                f.path.display(), config, include_in_build, is_excluded, should_include);
                            None
                        }
                    })
                    .collect();

                if !config_specific_files.is_empty() {
                    target_content.push_str(&self.generate_file_list("add_files", &config_specific_files, 2));
                }
            }

            // Qt 特定的文件处理
            if settings.qt_settings.enabled {
                self.add_qt_files(&mut target_content, &settings.qt_settings, output_dir);
            }

            // 处理字符集设置
            if let Some(character_set) = &settings.character_set {
                match character_set.as_str() {
                    "Unicode" => {
                        target_content.push_str("        add_defines(\"UNICODE\", \"_UNICODE\")\n");
                    }
                    "MultiByte" => {
                        // MultiByte 通常不需要额外的宏定义
                    }
                    _ => {}
                }
            }

            // 处理MFC设置
            if let Some(use_of_mfc) = &settings.use_of_mfc {
                match use_of_mfc.as_str() {
                    "Dynamic" => {
                        target_content.push_str("        add_defines(\"_AFXDLL\")\n");
                        target_content.push_str("        add_syslinks(\"mfc140\", \"mfcs140\")\n");
                    }
                    "Static" => {
                        target_content.push_str("        add_syslinks(\"uafxcw\", \"libcmt\")\n");
                    }
                    "false" => {
                        // 不使用MFC
                    }
                    _ => {}
                }
            }

            // 添加预处理器定义
            if !settings.preprocessor_definitions.is_empty() {
                target_content.push_str(&self.generate_file_list(
                    "add_defines",
                    &settings.preprocessor_definitions,
                    2,
                ));
            }

            // 添加包含目录
            if !settings.include_directories.is_empty() {
                let include_dirs: Vec<String> = settings
                    .include_directories
                    .iter()
                    .filter_map(|dir| dir.to_str().map(|s| s.replace('\\', "/")))
                    .collect();
                target_content.push_str(&self.generate_file_list(
                    "add_includedirs",
                    &include_dirs,
                    2,
                ));
            }

            // 添加链接目录
            if !settings.library_directories.is_empty() {
                let lib_dirs: Vec<String> = settings
                    .library_directories
                    .iter()
                    .filter_map(|dir| dir.to_str().map(|s| s.replace('\\', "/")))
                    .collect();
                target_content.push_str(&self.generate_file_list("add_linkdirs", &lib_dirs, 2));
            }

            // 添加链接库
            if !settings.libraries.is_empty() {
                target_content.push_str(&self.generate_file_list(
                    "add_links",
                    &settings.libraries,
                    2,
                ));
            }

            // 添加编译器标志
            if !settings.compiler_flags.is_empty() {
                target_content.push_str(&self.generate_file_list(
                    "add_cxflags",
                    &settings.compiler_flags,
                    2,
                ));
            }

            // 添加链接器标志
            if !settings.linker_flags.is_empty() {
                target_content.push_str(&self.generate_file_list(
                    "add_ldflags",
                    &settings.linker_flags,
                    2,
                ));
            }

            // 设置输出目录
            if let Some(output_dir) = &settings.output_directory {
                if let Some(path_str) = output_dir.to_str() {
                    let normalized_path = path_str.replace('\\', "/");
                    target_content
                        .push_str(&format!("        set_targetdir(\"{}\")\n", normalized_path));
                }
            }

            target_content.push_str("    end\n");
        }

        // 添加依赖项
        if !project.dependencies.is_empty() {
            target_content.push_str(&self.generate_file_list("add_deps", &project.dependencies, 1));
        }

        Ok(target_content)
    }

    fn map_qt_module(&self, module: &str) -> String {
        match module.to_lowercase().as_str() {
            "core" => "Core",
            "gui" => "Gui",
            "widgets" => "Widgets",
            "network" => "Network",
            "sql" => "Sql",
            "multimedia" => "Multimedia",
            "concurrent" => "Concurrent",
            "opengl" => "OpenGL",
            "xml" => "Xml",
            "svg" => "Svg",
            "webengine" => "WebEngine",
            "webenginewidgets" => "WebEngineWidgets",
            "websockets" => "WebSockets",
            "serialport" => "SerialPort",
            "bluetooth" => "Bluetooth",
            "quick" => "Quick",
            "quickwidgets" => "QuickWidgets",
            "qml" => "Qml",
            "charts" => "Charts",
            "datavisualization" => "DataVisualization",
            _ => module, // 如果无法映射，使用原名称
        }
        .to_string()
    }

    fn add_qt_files(
        &self,
        target_content: &mut String,
        qt_settings: &QtSettings,
        output_dir: &Path,
    ) {
        // 添加 moc 文件
        if !qt_settings.moc_files.is_empty() {
            target_content.push_str(&self.generate_path_file_list(
                "add_files",
                &qt_settings.moc_files,
                output_dir,
                2,
            ));
        }

        // 添加来自 CustomBuild 的 MOC 文件
        if !qt_settings.custom_moc_files.is_empty() {
            target_content.push_str("        -- Custom MOC files\n");
            let custom_moc_paths: Vec<PathBuf> = qt_settings.custom_moc_files
                .iter()
                .map(|custom_moc| custom_moc.source_file.clone())
                .collect();
            target_content.push_str(&self.generate_path_file_list(
                "add_files",
                &custom_moc_paths,
                output_dir,
                2,
            ));
        }

        // 添加 UI 文件
        if !qt_settings.ui_files.is_empty() {
            target_content.push_str(&self.generate_path_file_list(
                "add_files",
                &qt_settings.ui_files,
                output_dir,
                2,
            ));
        }

        // 添加 Qt 资源文件
        if !qt_settings.resource_files.is_empty() {
            target_content.push_str(&self.generate_path_file_list(
                "add_files",
                &qt_settings.resource_files,
                output_dir,
                2,
            ));
        }
    }

}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::core::{BuildSettings, SourceFile};
    use std::path::PathBuf;

    #[test]
    fn test_generate_simple_executable() {
        let generator = XmakeGenerator::new();
        let mut project = Project::new("test_app".to_string(), ProjectType::Executable);

        project.source_files.push(SourceFile::new(PathBuf::from("src/main.cpp")));

        let mut debug_settings = BuildSettings::default();
        debug_settings
            .preprocessor_definitions
            .push("DEBUG".to_string());
        debug_settings.language_standard = Some("c++17".to_string());
        project
            .configurations
            .insert(BuildConfiguration::Debug, debug_settings);

        let mut solution = Solution::new("TestSolution".to_string());
        solution.projects.push(project);

        let result = generator.generate_xmake_lua(&solution, &PathBuf::from("."));
        assert!(result.is_ok());

        let content = result.unwrap();
        assert!(content.contains("target(\"test_app\")"));
        assert!(content.contains("set_kind(\"binary\")"));
        assert!(content.contains("src/main.cpp"));
        assert!(content.contains("DEBUG"));
        assert!(content.contains("set_languages(\"c++17\")"));
    }

    #[test]
    fn test_generate_with_custom_moc_files() {
        use crate::core::*;
        use std::path::PathBuf;
        
        let generator = XmakeGenerator::new();
        
        // 创建包含 CustomBuild MOC 文件的项目
        let mut project = Project::new("test_custom_moc".to_string(), ProjectType::Executable);
        
        // 添加 CustomBuild 规则
        let custom_moc = CustomBuildRule {
            source_file: PathBuf::from("src/ClearThread/clearthread.h"),
            command: "$(QTDIR)/bin/moc.exe".to_string(),
            outputs: vec![PathBuf::from("GeneratedFiles/Debug/moc_clearthread.cpp")],
            additional_inputs: vec!["$(QTDIR)/bin/moc.exe".to_string()],
            message: Some("Moc'ing clearthread.h...".to_string()),
            is_moc_file: true,
        };
        project.custom_build_rules.push(custom_moc.clone());
        
        // 设置 Qt 配置
        let mut qt_settings = QtSettings::default();
        qt_settings.enabled = true;
        qt_settings.version = Some("5.15.2".to_string());
        qt_settings.modules = vec!["core".to_string(), "gui".to_string(), "widgets".to_string()];
        qt_settings.custom_moc_files.push(custom_moc);
        
        let mut settings = BuildSettings::default();
        settings.qt_settings = qt_settings;
        settings.language_standard = Some("c++17".to_string());
        
        project.configurations.insert(BuildConfiguration::Debug, settings);
        
        let mut solution = Solution::new("TestSolution".to_string());
        solution.projects.push(project);
        
        let result = generator.generate_xmake_lua(&solution, &PathBuf::from("."));
        assert!(result.is_ok());
        
        let content = result.unwrap();
        assert!(content.contains("target(\"test_custom_moc\")"));
        assert!(content.contains("add_rules(\"qt.widgetapp\")"));
        assert!(content.contains("set_values(\"qt.version\", \"5.15.2\")"));
        assert!(content.contains("-- Custom MOC files"));
        assert!(content.contains("clearthread.h"));
        assert!(content.contains("set_languages(\"c++17\")"));
        
        println!("Generated xmake.lua content:\n{}", content);
    }

    #[test]
    fn test_generate_with_excluded_files() {
        let generator = XmakeGenerator::new();
        let mut project = Project::new("test_app".to_string(), ProjectType::Executable);

        // 添加源文件，其中一些在特定配置中被排除
        let main_file = SourceFile::new(PathBuf::from("src/main.cpp"));
        project.source_files.push(main_file);
        
        // 添加一个在特定配置中被排除的非MOC文件
        let mut debug_only_file = SourceFile::new(PathBuf::from("src/debug_helper.cpp"));
        debug_only_file.set_excluded_in_config(BuildConfiguration::Release, true);
        project.source_files.push(debug_only_file);
        
        let mut release_only_file = SourceFile::new(PathBuf::from("src/optimized.cpp"));
        release_only_file.set_excluded_in_config(BuildConfiguration::Debug, true);
        project.source_files.push(release_only_file);

        let mut debug_settings = BuildSettings::default();
        debug_settings.preprocessor_definitions.push("DEBUG".to_string());
        project.configurations.insert(BuildConfiguration::Debug, debug_settings);

        let mut release_settings = BuildSettings::default();
        release_settings.preprocessor_definitions.push("NDEBUG".to_string());
        project.configurations.insert(BuildConfiguration::Release, release_settings);

        let mut solution = Solution::new("TestSolution".to_string());
        solution.projects.push(project);

        let output_path = Path::new(".");
        let xmake_content = generator.generate_xmake_lua(&solution, output_path).unwrap();

        // 验证生成的内容包含配置特定的文件
        assert!(xmake_content.contains("if is_mode(\"debug\") then"));
        assert!(xmake_content.contains("if is_mode(\"release\") then"));
        
        // 在Debug配置中应该包含main.cpp和debug专用文件，但不包含release专用文件
        let debug_section = extract_section(&xmake_content, "if is_mode(\"debug\") then", "end");
        assert!(debug_section.contains("src/main.cpp"));
        assert!(debug_section.contains("src/debug_helper.cpp"));
        assert!(!debug_section.contains("src/optimized.cpp"));
        
        // 在Release配置中应该包含main.cpp和release专用文件，但不包含debug专用文件
        let release_section = extract_section(&xmake_content, "if is_mode(\"release\") then", "end");
        assert!(release_section.contains("src/main.cpp"));
        assert!(!release_section.contains("src/debug_helper.cpp"));
        assert!(release_section.contains("src/optimized.cpp"));
    }

    #[test]
    fn test_generate_with_property_group_attributes() {
        let generator = XmakeGenerator::new();
        let mut project = Project::new("test_app".to_string(), ProjectType::Executable);

        project.source_files.push(SourceFile::new(PathBuf::from("src/main.cpp")));

        let mut debug_settings = BuildSettings::default();
        debug_settings.character_set = Some("Unicode".to_string());
        debug_settings.use_of_mfc = Some("Dynamic".to_string());
        debug_settings.platform_toolset = Some("v141".to_string());
        project.configurations.insert(BuildConfiguration::Debug, debug_settings);

        let mut release_settings = BuildSettings::default();
        release_settings.character_set = Some("MultiByte".to_string());
        release_settings.use_of_mfc = Some("false".to_string());
        release_settings.platform_toolset = Some("v120".to_string());
        project.configurations.insert(BuildConfiguration::Release, release_settings);

        let mut solution = Solution::new("TestSolution".to_string());
        solution.projects.push(project);

        let output_path = Path::new(".");
        let xmake_content = generator.generate_xmake_lua(&solution, output_path).unwrap();

        // 验证Unicode字符集的宏定义
        let debug_section = extract_section(&xmake_content, "if is_mode(\"debug\") then", "end");
        assert!(debug_section.contains("add_defines(\"UNICODE\", \"_UNICODE\")"));
        assert!(debug_section.contains("add_defines(\"_AFXDLL\")"));
        assert!(debug_section.contains("add_syslinks(\"mfc140\", \"mfcs140\")"));
        
        // 验证Release配置不包含Unicode宏定义（因为是MultiByte）
        let release_section = extract_section(&xmake_content, "if is_mode(\"release\") then", "end");
        assert!(!release_section.contains("add_defines(\"UNICODE\", \"_UNICODE\")"));
        assert!(!release_section.contains("_AFXDLL"));
    }
    
    // 辅助函数：提取配置段落内容
    fn extract_section(content: &str, start_marker: &str, end_marker: &str) -> String {
        let start_pos = content.find(start_marker).unwrap_or(0);
        let end_pos = content[start_pos..].find(end_marker)
            .map(|pos| start_pos + pos)
            .unwrap_or(content.len());
        content[start_pos..end_pos].to_string()
    }

    #[test]
    fn test_normalize_path_unc_prefix() {
        let unc = Path::new(r"\\?\UNC\server\share\project.sln");
        let normalized = XmakeGenerator::normalize_path(unc);
        assert_eq!(normalized.to_string_lossy(), r"\\server\share\project.sln");

        let drive = Path::new(r"\\?\C:\\work\\project.sln");
        let normalized_drive = XmakeGenerator::normalize_path(drive);
        assert_eq!(normalized_drive.to_string_lossy(), r"C:\\work\\project.sln");
    }

    #[test]
    fn test_generate_code_style_files() {
        use crate::config::CodeStyleConfig;
        use tempfile::TempDir;

        let temp_dir = TempDir::new().unwrap();
        let project_root = temp_dir.path();

        let generator = XmakeGenerator::new();

        // 测试默认配置（生成两个文件）
        let config = CodeStyleConfig::default();
        generator.generate_code_style_files(project_root, &config).unwrap();

        let clang_format_path = project_root.join(".clang-format");
        let clang_tidy_path = project_root.join(".clang-tidy");

        assert!(clang_format_path.exists(), ".clang-format 文件应该被创建");
        assert!(clang_tidy_path.exists(), ".clang-tidy 文件应该被创建");

        // 验证文件内容不为空
        let format_content = std::fs::read_to_string(&clang_format_path).unwrap();
        let tidy_content = std::fs::read_to_string(&clang_tidy_path).unwrap();

        assert!(!format_content.is_empty(), ".clang-format 内容不应该为空");
        assert!(!tidy_content.is_empty(), ".clang-tidy 内容不应该为空");

        // 验证内容包含预期的配置
        assert!(format_content.contains("BasedOnStyle"), ".clang-format 应该包含 BasedOnStyle");
        assert!(tidy_content.contains("Checks:"), ".clang-tidy 应该包含 Checks");
    }

    #[test]
    fn test_generate_code_style_files_disabled() {
        use crate::config::CodeStyleConfig;
        use tempfile::TempDir;

        let temp_dir = TempDir::new().unwrap();
        let project_root = temp_dir.path();

        let generator = XmakeGenerator::new();

        // 测试禁用 clang-format
        let mut config = CodeStyleConfig::default();
        config.generate_clang_format = false;
        generator.generate_code_style_files(project_root, &config).unwrap();

        let clang_format_path = project_root.join(".clang-format");
        let clang_tidy_path = project_root.join(".clang-tidy");

        assert!(!clang_format_path.exists(), ".clang-format 不应该被创建");
        assert!(clang_tidy_path.exists(), ".clang-tidy 应该被创建");
    }

    #[test]
    fn test_generate_code_style_files_all_disabled() {
        use crate::config::CodeStyleConfig;
        use tempfile::TempDir;

        let temp_dir = TempDir::new().unwrap();
        let project_root = temp_dir.path();

        let generator = XmakeGenerator::new();

        // 测试全部禁用
        let mut config = CodeStyleConfig::default();
        config.generate_clang_format = false;
        config.generate_clang_tidy = false;
        generator.generate_code_style_files(project_root, &config).unwrap();

        let clang_format_path = project_root.join(".clang-format");
        let clang_tidy_path = project_root.join(".clang-tidy");

        assert!(!clang_format_path.exists(), ".clang-format 不应该被创建");
        assert!(!clang_tidy_path.exists(), ".clang-tidy 不应该被创建");
    }
}
